#include "SentenceBlockBuilder.h"

#include "ScriptCompiler/AST/SentenceBlockNode.h"
#include "ScriptCompiler/ScriptFileContext.h"

#include "SentenceBuilder.h"

CSentenceBlockBuilder::CSentenceBlockBuilder(
    std::shared_ptr<CScriptFileContext> InContext
    ,int32_t InEndTokenIndex
    )
{
    Context = InContext;
    Result = std::make_shared<CSentenceBlockNode>(Context);
    EndTokenIndex = InEndTokenIndex;

}

bool CSentenceBlockBuilder::ReadCurentToken()
{
    while(Context->CurrentTokenIndex<EndTokenIndex)
    {
        //read '{'
        {
            auto Token = Context->GetCurrentToken();
            if (Token->Type != EScriptTokenType::LeftBrace)
            {
                //this is a single  sentence without brace

                //try read a sentence
                auto SentenceBuilder=std::make_shared<CSentenceBuilder>(Context);

                bool Succeed= SentenceBuilder->ReadCurentToken();
                if(!Succeed)
                {
                    return false;
                }

                //check if this is a empty sentence
                if(SentenceBuilder->Result)
                {
                    Result->Sentences.Add(SentenceBuilder->Result);
                }

                continue;
            }
            Context->CurrentTokenIndex++;
        }

        //find '}'
        uint64_t RightBraceIndex;
        {
            auto RightBracePos = FindPairedBrace(Context);
            if (!RightBracePos)
            {
                //raise error, require '}'
                Context->RaiseError(10090,Context->GetCurrentToken(), U"Expected paired '}' ");
                return false;
            }
            RightBraceIndex = *RightBracePos;

            if(RightBraceIndex>EndTokenIndex)
            {
                //raise error, require '}'
                Context->RaiseError(10146,Context->GetCurrentToken(), U"Expected paired '}' ");
                return false;
            }
        }

        auto SubBlockBuilder=std::make_shared<CSentenceBlockBuilder>(Context,RightBraceIndex);
        SubBlockBuilder->Result->HaveBrace=true;
        if(!SubBlockBuilder->ReadCurentToken())
        {
            return false;
        }
        Result->Sentences.Add(SubBlockBuilder->Result);

        //skip '}'
        assert(Context->CurrentTokenIndex == RightBraceIndex);
        Context->CurrentTokenIndex++;

    }
    return true;
}

// bool CSentenceBlockBuilder::ReadNextSentence()
// {
//     auto Token = Context->GetCurrentToken();

//     switch(Token->Type)
//     {
//         case EScriptTokenType::If:
//         {
//             auto IfBuilder = std::make_shared<CIfBuilder>(Context);
//             if (!IfBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(IfBuilder->Result);
//             return true;
//         }

//         case EScriptTokenType::Switch:
//         {
//             auto SwitchBuilder = std::make_shared<CSwitchBuilder>(Context);
//             if (!SwitchBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(SwitchBuilder->Result);
//             return true;
//         }

//         case EScriptTokenType::While:
//         {
//             auto WhileBuilder = std::make_shared<CWhileBuilder>(Context);
//             if (!WhileBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(WhileBuilder->Result);
//             return true;
//         }

//         case EScriptTokenType::Do:
//         {
//             auto DowhileBuilder = std::make_shared<CDoWhileBuilder>(Context);
//             if (!DowhileBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(DowhileBuilder->Result);
//             return true;
//         }

//         case EScriptTokenType::For:
//         {
//             auto ForBuilder = std::make_shared<CForBuilder>(Context);
//             if (!ForBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(ForBuilder->Result);
//             return true;
//         }

//         case EScriptTokenType::Return:
//         {
//             auto ReturnBuilder = std::make_shared<CReturnBuilder>(Context);
//             if (!ReturnBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(ReturnBuilder->Result);
//             return true;
//         }

//         case EScriptTokenType::Break:
//         {
//             auto BreakBuilder = std::make_shared<CBreakBuilder>(Context);
//             if (!BreakBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(BreakBuilder->Result);
//             return true;
//         }

//         case  EScriptTokenType::Continue:
//         {
//             auto ContinueBuilder = std::make_shared<CContinueBuilder>(Context);
//             if (!ContinueBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             Result->Sentences.Add(ContinueBuilder->Result);
//             return true;
//         }

//         default:
//         {
//             //test if this is a variable declaration
//             if(CVariableDecalarationBuilder::DetectVariableDeclaration(Context))
//             {
//                 auto VariableDeclarationBuilder = std::make_shared<CVariableDecalarationBuilder>(Context);
//                 if (!VariableDeclarationBuilder->ReadCurentToken())
//                 {
//                     return false;
//                 }
//                 Result->Sentences.Add(VariableDeclarationBuilder->Result);
//                 return true;
//             }


//             //next sentence is ended by ';'
//             //find ';'
//             auto SemiColonIndex = FindNextToken(EScriptTokenType::Semicolon, Context);
//             if (!SemiColonIndex.HasValue())
//             {
//                 Context->RaiseError(10091,Context->GetCurrentToken(), U"Expect ';' at end of sentence");
//                 return false;
//             }

//             auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context, SemiColonIndex.GetValue());
//             if (!ExpressionBuilder->ReadCurentToken())
//             {
//                 return false;
//             }
//             if(ExpressionBuilder->Result->Type!=EASTNodeType::Empty)
//             {
//                 std::shared_ptr<CExpressionSentence> SentenceNode = std::make_shared<CExpressionSentence>(Context);
//                 SentenceNode->Expression=ExpressionBuilder->Result;
//                 Result->Sentences.Add(SentenceNode);
//             }

//             //skip ';'
//             assert(SemiColonIndex.GetValue() == Context->CurrentTokenIndex);
//             Context->CurrentTokenIndex++;

//             return true;
//         }
//     }

//     assert(false && "unreachable" );
//     return false;
// }

